<?php
/**
 * @file
 */

/**
 * Implements of hook_entity_info()
 */
function wordgame_word_entity_info() {
  $return = array(
    'wordgame_word' => array(
      'label' => t('Words'),
      'controller class' => 'WordGameWordController',
      'base table' => 'wordgame_word',
      'uri callback' => 'wordgame_word_uri',
      'fieldable' => TRUE,
      'entity keys' => array(
        'id' => 'wid',
      ),
      'bundles' => array(
        'wordgame_word' => array(
          'label' => t('Words'),
          'admin' => array(
            'path' => 'admin/config/wordgame/words',
            'access arguments' => array('administer wordgame'),
          ),
        ),
      ),
      'view modes' => array(
        'full' => array(
          'label' => t('Words'),
          'custom settings' => FALSE,
        ),
      ),
    ),
  );
  return $return;
}

/**
 * Implements callback_entity_info_uri().
 */
function wordgame_word_uri($wordgame) {
  return array(
    'path' => 'wordgame/word/' . $wordgame->wid,
    'options' => array('fragment' => 'wordgame-word-' . $wordgame->wid),
  );
}

/**
 * Implements hook_field_info_alter().
 */
function wordgame_word_client_field_info_alter(&$info) {
  // Add the 'wordgame_word_form' instance setting to all field types.
  foreach ($info as $field_type => &$field_type_info) {
    $field_type_info += array('instance_settings' => array());
    $field_type_info['instance_settings'] += array(
      'wordgame_word_edit' => FALSE,
    );
  }
}

/**
 * Implements hook_field_extra_fields().
 */
function wordgame_word_field_extra_fields() {
  $return['wordgame_word']['wordgame_word'] = array(
    'form' => array(
      'word' => array(
        'label' => t('Word'),
        'description' => t('wordgame_word module word form elements.'),
        'weight' => -10,
      ),
      'status' => array(
        'label' => t('Status'),
        'description' => t('wordgame_word module status form element.'),
        'weight' => 6,
      ),
    ),
    'display' => array(
      'summary' => array(
        'label' => t('Words'),
        'description' => t('wordgame_word module client view element.'),
        'weight' => 5,
      ),
    ),
  );

  return $return;
}

/**
 * Load the entire word by wid.
 *
 * @param $wid
 *   The identifying comment id.
 * @param $reset
 *   Whether to reset the internal static entity cache. Note that the static
 *   cache is disabled in comment_entity_info() by default.
 *
 * @return
 *   The comment object.
 */
function wordgame_word_load($wid, $reset = FALSE) {
  $word = wordgame_word_load_multiple(array($wid), array(), $reset);
  return $word ? $word[$wid] : FALSE;
}

/**
 * Load word from the database.
 *
 * @param $wids
 *   An array of word IDs.
 * @param $conditions
 *   (deprecated) An associative array of conditions on the {wordgames}
 *   table, where the keys are the database fields and the values are the
 *   values those fields must have. Instead, it is preferable to use
 *   EntityFieldQuery to retrieve a list of entity IDs loadable by
 *   this function.
 * @param $reset
 *   Whether to reset the internal static entity cache. Note that the static
 *   cache is disabled in wordgame_entity_info() by default.
 *
 * @return
 *   An array of comment objects, indexed by word ID.
 *
 * @see entity_load()
 * @see EntityFieldQuery
 *
 * @todo Remove $conditions in Drupal 8.
 */
function wordgame_word_load_multiple($wids = array(), $conditions = array(), $reset = FALSE) {
  return entity_load('wordgame_word', $wids, $conditions, $reset);
}

/**
 *
 */
function wordgame_word_load_multiple_extra($char, $border, $exclude = array(), $min_length = 4) {
  $query = "SELECT * FROM {wordgame_word} d WHERE d.word LIKE '%%{$char}%%' AND LOCATE(' ', d.word) = 0";
  $query .= " AND LOCATE('{$char}', d.word) < {$border['first']}";
  $query .= " AND (LENGTH(d.word) - LOCATE('{$char}', d.word)) < {$border['after']}";
  $query .= " AND (d.length >= {$min_length})";
  $result = db_query($query);
  $records = array();
  $index = 0;
  foreach ($result as $record) {
    if (!empty($exclude)) {
      if (in_array($record->word, $exclude)) {
        continue ;
      }
    }
    $records[$index++] = $record;
  }
  return $records;
}



/**
 * Save word
 */
function wordgame_word_save($word) {
  $transaction = db_transaction();

  try {
    field_attach_presave('wordgame_word', $word);

    // Determine if we will be inserting a new node.
    if (!isset($word->is_new)) {
      $word->is_new = empty($word->wid);
    }

    $word->modified = REQUEST_TIME;

    // Let modules modify the node before it is saved to the database.
    module_invoke_all('wordgame_word_presave', $word);
    module_invoke_all('entity_presave', $word, 'wordgame_word');

    // Save the node and node revision.
    if ($word->is_new) {
      // For new wordgame_word, save new records for the wordgame_word itself      
      drupal_write_record('wordgame_word', $word);
      $op = 'insert';
    }
    else {
      // For existing wordgame_word, update the wordgame_word record which matches the value of
      // $wordgame_word->wid.
      drupal_write_record('wordgame_word', $word, 'wid');
      $op = 'update';
    }

    // Save fields.
    $function = "field_attach_$op";
    $function('wordgame_word', $word);

    module_invoke_all('wordgame_word_' . $op, $word);
    module_invoke_all('entity_' . $op, $word, 'wordgame_word');

    // Clear internal properties.
    unset($word->is_new);
    // Clear the static loading cache.
    entity_get_controller('wordgame_word')->resetCache(array($word->wid));

    // Ignore slave server temporarily to give time for the
    // saved wordgame_word to be propagated to the slave.
    db_ignore_slave();
  }
  catch (Exception $e) {
    $transaction->rollback();
    watchdog_exception('wordgame_word', $e);
    throw $e;
  }
}

/**
 * Deletes a wordgame word.
 *
 * @param $cid
 *   A wordgame_word ID.
 */
function wordgame_word_delete($wid) {
  wordgame_word_delete_multiple(array($wid));
}

/**
 * Deletes multiple words.
 *
 * @param $cids
 *   An array of word IDs.
 */
function wordgame_word_delete_multiple($wids) {
  $transaction = db_transaction();
  if (!empty($wids)) {
    $words = wordgame_word_load_multiple($wids, array());

    try {
      foreach ($words as $wid => $word) {
        // Call the node-specific callback (if any):
        module_invoke_all('wordgame_word_delete', $word);
        module_invoke_all('entity_delete', $word, 'wordgame_word');
        field_attach_delete('wordgame_word', $word);
      }
      // Delete after calling hooks so that they can query wordgame_word tables as needed.
      db_delete('wordgame_word')
        ->condition('wid', $wids, 'IN')
        ->execute();
    }
    catch (Exception $e) {
      $transaction->rollback();
      watchdog_exception('wordgame_word', $e);
      throw $e;
    }

    // Clear the page and block and node_load_multiple caches.
    entity_get_controller('wordgame_word')->resetCache();
  }
}

/**
 * Controller class for wordgame word.
 *
 * This extends the DrupalDefaultEntityController class, adding required
 * special handling for comment objects.
 */
class WordGameWordController extends DrupalDefaultEntityController {
  protected function attachLoad(&$words, $revision_id = FALSE) {
    // Call the default attachLoad() method. This will add fields and call
    // hook_wordgame_load().
    parent::attachLoad($words, $revision_id);
  }
}
